﻿using LearnMAUI2.Models;
using System.Linq.Expressions;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace LearnMAUI2.Services;
public class TodayPoetryService : ITodayPoetryService
{
    private readonly IAlertService _alertService;
    private readonly IPoetryStorage _poetryStorage;
    private readonly IPreferenceStorage _preferenceStorage;

    public TodayPoetryService(IAlertService alertService, IPoetryStorage poetryStorage,IPreferenceStorage preferenceStorage)
    {
        _alertService = alertService;
        _poetryStorage = poetryStorage;
        _preferenceStorage = preferenceStorage;
    }

    public async Task<TodayPoetry> GetRandomPoetryAsync()
    {
        //随机取1条
        var poetries = await _poetryStorage.GetPoetriesAsync(
            Expression.Lambda<Func<Poetry, bool>>(Expression.Constant(true),
            Expression.Parameter(typeof(Poetry))),
            new Random().Next(30), 1);
        var poetry = poetries.First();

        return new TodayPoetry
        {
            Snippet = poetry.Snippet,
            Name = poetry.Name,
            Dynasty = poetry.Dynasty,
            Author = poetry.Author,
            Content = poetry.Content,
            Source = TodayPoetrySources.Local
        };
    }

    public async Task<TodayPoetry> GetTodayPoetryAsync()
    {
        var token = await GetTokenAsync();
        using var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Add("X-User-Token", token);
        HttpResponseMessage response;
        PoetrySentenceDeserialize poetryDeserialize;
        if (string.IsNullOrWhiteSpace(token))
        {
            return await GetRandomPoetryAsync();
        }
        try
        {
            var responseMessage = await httpClient.GetAsync("https://v2.jinrishici.com/sentence");
            var json = await responseMessage.Content.ReadAsStringAsync();
            poetryDeserialize = JsonSerializer.Deserialize<PoetrySentenceDeserialize>(json, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            }) ?? throw new JsonException();
            return new TodayPoetry
            {
                Snippet = poetryDeserialize.data?.content ?? throw new JsonException(),
                Name = poetryDeserialize.data.origin?.title ?? throw new JsonException(),
                Author = poetryDeserialize.data.origin?.author ?? throw new JsonException(),
                Dynasty = poetryDeserialize.data.origin?.dynasty ?? throw new JsonException(),
                Content = string.Join("\n", poetryDeserialize.data.origin?.content ?? throw new JsonException()),
                Source = TodayPoetrySources.Remote
            };
        }
        catch (Exception ex)
        {
            _alertService.Alert("Error", ex.Message, "Ok");
            return await GetRandomPoetryAsync();
        }

    }

    private const string CurrentToken = nameof(CurrentToken) + ".Token";

    public async Task<string> GetTokenAsync()
    {
        var localToken = _preferenceStorage.Get(CurrentToken, string.Empty);
        if (!string.IsNullOrWhiteSpace(localToken))
            return localToken;

        //注意正常情况下不要生成过多的HttpClient，客户端少量可以，服务端不能这么写,另外GetAsync(string url)也容易因为服务器无法访问而崩溃
        using var httpClient = new HttpClient();
        HttpResponseMessage response;
        try
        {
            response = await httpClient.GetAsync("https://v2.jinrishici.com/token");
            //确保返回码一定是200.不是就异常
            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync();
            var token = JsonSerializer.Deserialize<PoetryToken>(json);
            if (token != null)
            {
                localToken = token.data;
                _preferenceStorage.Set(CurrentToken, localToken);
                return token.data;
            }
            return string.Empty;
        }
        catch (Exception ex)
        {
            _alertService.Alert("Error", ex.Message, "Ok");
            return string.Empty;
        }
    }

    public class PoetryToken
    {
        public string status { get; set; }
        public string data { get; set; }
    }


    public class PoetrySentenceDeserialize
    {
        public string status { get; set; }
        public Data data { get; set; }
        public string token { get; set; }
        public string ipAddress { get; set; }
    }

    public class Data
    {
        public string id { get; set; }
        public string content { get; set; }
        public int popularity { get; set; }
        public Origin origin { get; set; }
        public string[] matchTags { get; set; }
        public string recommendedReason { get; set; }
        public DateTime cacheAt { get; set; }
    }

    public class Origin
    {
        public string title { get; set; }
        public string dynasty { get; set; }
        public string author { get; set; }
        public string[] content { get; set; }
        public string[] translate { get; set; }
    }

}
